#include "stdafx.h"
#include "XButtonImpl.h"

#include "Util.h"
#include "UIUtil.h"
#include "DrawUtil.h"

#include "IntSkinImpl.h"

template <class I>
CXButtonImpl<I>::CXButtonImpl()
{
    m_pButtonDraw = NULL;
    ModifyControlFlags(ESkin_CanHover, TRUE);
    ModifyControlFlags(ESkin_Interactive, TRUE);
#if _IS_UI_FOCUS_ENABLED_
    ModifyControlFlags(ESkin_NeedKeyMsg, TRUE);
#endif // _IS_UI_FOCUS_ENABLED_
}

template <class I>
CXButtonImpl<I>::~CXButtonImpl()
{
}

//////////////////////////////////////////////////////////////////////////
// IXButton

template <class I>
HRESULT CXButtonImpl<I>::put_Draw(IN IXButtonDraw* pDraw)
{
    XSAFE_RELEASE(m_pButtonDraw);
    m_pButtonDraw = pDraw;
    m_pButtonDraw->AddRef();
    OnImageChanged();

    AutoSizeImpl(FALSE);
    return S_OK;
}

template <class I>
HRESULT CXButtonImpl<I>::put_ImagePath(IN LPCTSTR szXNC, IN INT nHCount, IN INT nVCount, IN ImageDrawParams* pParam)
{
    XSAFE_RELEASE(m_pButtonDraw);
    HRESULT hResult = Util::CreateObject(&m_pButtonDraw);
    if(SUCCEEDED(hResult))
    {
        hResult = m_pButtonDraw->put_ImagePath(szXNC);
        if(SUCCEEDED(hResult))
        {
            hResult = m_pButtonDraw->put_SubCount(nHCount, nVCount);
            m_pButtonDraw->put_DrawParams(pParam);
            OnImageChanged();
            AutoSizeImpl(FALSE);
            Invalidate();
        }
    }
    return hResult;
}

template <class I>
HRESULT CXButtonImpl<I>::get_ImagePath(OUT BSTR* pbstrXNC, OUT INT* pnHCount, OUT INT* pnVCount, OUT ImageDrawParams* pParam)
{
    if(m_pButtonDraw == NULL)
        return E_FAIL;

    HRESULT hResult = m_pButtonDraw->get_ImagePath(pbstrXNC);
    CHECK_HRESULT(hResult);

    hResult = m_pButtonDraw->get_SubCount(pnHCount, pnVCount);
    CHECK_HRESULT(hResult);

    hResult = m_pButtonDraw->get_DrawParams(pParam);
    CHECK_HRESULT(hResult);

    return hResult;
}

template <class I>
HRESULT CXButtonImpl<I>::put_DrawParams(IN ImageDrawParams* pParam)
{
    NeedImage();
    if(m_pButtonDraw == NULL)
        return E_FAIL;
    else
        return m_pButtonDraw->put_DrawParams(pParam);
}

template <class I>
HRESULT CXButtonImpl<I>::get_DrawParams(OUT ImageDrawParams* pParam)
{
    NeedImage();
    if(m_pButtonDraw == NULL)
        return E_FAIL;
    else
        return m_pButtonDraw->get_DrawParams(pParam);
}

template <class I>
HRESULT CXButtonImpl<I>::put_AlphaMode(IN eImageAlphaMode nAlphaMode)
{
    NeedImage();
    if(m_pButtonDraw == NULL)
        return E_FAIL;
    else
        return m_pButtonDraw->put_AlphaMode(nAlphaMode);
}

template <class I>
HRESULT CXButtonImpl<I>::get_AlphaMode(OUT eImageAlphaMode* pnAlphaMode)
{
    NeedImage();
    if(m_pButtonDraw == NULL)
        return E_FAIL;
    else
        return m_pButtonDraw->get_AlphaMode(pnAlphaMode);
}

template <class I>
HRESULT CXButtonImpl<I>::put_AlphaValue(IN BYTE byAlphaValue)
{
    NeedImage();
    if(m_pButtonDraw == NULL)
        return E_FAIL;
    else
        return m_pButtonDraw->put_AlphaValue(byAlphaValue);
}

template <class I>
HRESULT CXButtonImpl<I>::get_AlphaValue(OUT LPBYTE pbyAlphaValue)
{
    NeedImage();
    if(m_pButtonDraw == NULL)
        return E_FAIL;
    else
        return m_pButtonDraw->get_AlphaValue(pbyAlphaValue);
}

template <class I>
HRESULT CXButtonImpl<I>::put_TransparentColor(IN COLORREF clrTrans)
{
    NeedImage();
    if(m_pButtonDraw == NULL)
        return E_FAIL;
    else
        return m_pButtonDraw->put_TransparentColor(clrTrans);
}

template <class I>
HRESULT CXButtonImpl<I>::get_TransparentColor(OUT LPCOLORREF pclrTrans)
{
    NeedImage();
    if(m_pButtonDraw == NULL)
        return E_FAIL;
    else
        return m_pButtonDraw->get_TransparentColor(pclrTrans);
}

//////////////////////////////////////////////////////////////////////////
// IXFrame
template <class I>
void CXButtonImpl<I>::GetAutoSize(OUT LPSIZE pAutoSize)
{
    NeedImage();
    if(m_pButtonDraw == NULL)
    {
        superclass::GetAutoSize(pAutoSize);
    }
    else
    {
        int nHorz = 0, nVert = 0;
        m_pButtonDraw->get_SubCount(&nHorz, &nVert);

        m_pButtonDraw->get_ImageSize(pAutoSize);
    }

    SIZE sizeText = {0};
    if(!m_strText.empty())
    {
        superclass::GetAutoSize(&sizeText);
        sizeText.cx += 4;
        sizeText.cy += 4;
    }

    pAutoSize->cx = max(pAutoSize->cx, sizeText.cx);
    pAutoSize->cy = max(pAutoSize->cy, sizeText.cy);
}

template <class I>
void CXButtonImpl<I>::Draw(XCANVAS xCanvas, const RECT& rcDraw)
{
    superclass::Draw(xCanvas, rcDraw);

    RECT rcWnd;
    get_WindowRect(&rcWnd);

    HRESULT hResult = S_OK;
    NeedImage();
    if(m_pButtonDraw != NULL)
    {
        hResult = m_pButtonDraw->Draw(xCanvas, &rcWnd);
    }

    if(!m_strText.empty())
    {
        IXFont* pFont = NULL;
        IXTextEnv* pTextEnv = NULL;

        get_Font(&pFont);
        get_TextEnv(&pTextEnv);

        if(TestControlFlags(ESkin_Down))
            ::OffsetRect(&rcWnd, 1, 1);

        DrawUtil::XDrawText(xCanvas, m_strText, m_strText.Length(), &rcWnd, pTextEnv, pFont);
    }
}

template <class I>
BOOL CXButtonImpl<I>::OnMouseDown(IN POINT* pt)
{
    if(TestControlFlags(ESkin_Hover))
    {
        superclass::OnMouseDown(pt);
        UpdateImageIndex();
    }
    return TRUE;
}

template <class I>
BOOL CXButtonImpl<I>::OnMouseUp(IN POINT* pt)
{
    BOOL bPress = TestControlFlags(ESkin_Down);
    if(bPress)
    {
        UpdateImageIndex();
    }
    superclass::OnMouseUp(pt);
    return TRUE;
}

template <class I>
BOOL CXButtonImpl<I>::OnMouseMove(IN POINT* pt)
{
    superclass::OnMouseMove(pt);
    UpdateImageIndex();
    return TRUE;
}

template <class I>
BOOL CXButtonImpl<I>::OnMouseHover(IN POINT* pt)
{
    superclass::OnMouseHover(pt);
    UpdateImageIndex();
    return TRUE;
}

template <class I>
BOOL CXButtonImpl<I>::OnMouseLeave(IN POINT* pt)
{
    if(TestControlFlags(ESkin_Hover))
    {
        if(UIUtil::IsKeyPressed(VK_LBUTTON))
        {
        }
        else
        {
            ModifyControlFlags(ESkin_Down, FALSE);
        }
        superclass::OnMouseLeave(pt);
        UpdateImageIndex();
    }
    return TRUE;
}

template <class I>
BOOL CXButtonImpl<I>::OnKeyDown(UINT uChar, UINT nRepCnt, UINT nFlags)
{
    if(uChar == VK_SPACE || uChar == VK_RETURN)
    {
        ModifyControlFlags(ESkin_Hover, TRUE);
        ModifyControlFlags(ESkin_Down, TRUE);
        UpdateImageIndex();
        return TRUE;
    }
    return FALSE;
}

template <class I>
BOOL CXButtonImpl<I>::OnKeyUp(UINT uChar, UINT nRepCnt, UINT nFlags)
{
    if(uChar == VK_SPACE || uChar == VK_RETURN)
    {
        ModifyControlFlags(ESkin_Down, FALSE);
        ModifyControlFlags(ESkin_Hover, FALSE);
        UpdateImageIndex();
        RECT rcWnd;
        get_WindowRect(&rcWnd);
        POINT Pt = {rcWnd.left, rcWnd.top};
        OnClicked(&Pt);
        return TRUE;
    }
    return FALSE;
}

//////////////////////////////////////////////////////////////////////////
// IXConfig
template <class I>
void CXButtonImpl<I>::SetEnable(BOOL bEnable)
{
    superclass::SetEnable(bEnable);
    UpdateImageIndex();
}

//////////////////////////////////////////////////////////////////////////
// IXBaseObj
template <class I>
void CXButtonImpl<I>::OnFinalRelease()
{
    superclass::OnFinalRelease();
    XSAFE_RELEASE(m_pButtonDraw);
}

//////////////////////////////////////////////////////////////////////////
// CXButtonImpl
template <class I>
void CXButtonImpl<I>::UpdateImageIndex()
{
    int nIndex = BI_Normal;
    NeedImage();
    if(m_pButtonDraw != NULL)
    {
        BOOL bEnabled = TestControlFlags(ESkin_Enabled);
        BOOL bDown = TestControlFlags(ESkin_Down);
        BOOL bHover = TestControlFlags(ESkin_Hover);

        if(!bEnabled)
            nIndex = BI_Disable;
        else if(bDown && bHover)
            nIndex = BI_Down;
        else if(bHover)
            nIndex = BI_Hover;
        else
            nIndex = BI_Normal;

        int nHorz = 0, nVert = 0;
        m_pButtonDraw->get_Index(&nHorz, &nVert);
        if(nHorz != nIndex)
        {
            m_pButtonDraw->put_Index(nIndex, nVert);
            Invalidate();
        }
    }
}

template <class I>
void CXButtonImpl<I>::NeedImage()
{
    if(m_pButtonDraw == NULL)
    {
        if(SUCCEEDED(Util::CreateObject(&m_pButtonDraw)))
        {
            m_pButtonDraw->put_ImagePath(_T("@skin:Common\\pushbutton.png"));
            m_pButtonDraw->put_SubCount(5, 1);
        }
    }
}

template <class I>
void CXButtonImpl<I>::OnImageChanged()
{
    ;
}
